home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Mac Format 1997 July
/
macformat52.iso
/
mac
/
Shareware Plus
/
Comms
/
ICeTEe 2
/
Source (for Programmers only)
/
ICeTEe.c
< prev
Wrap
C/C++ Source or Header
|
1997-04-09
|
12KB
|
517 lines
/* NAME:
ICeTEe.c
WRITTEN BY:
Michael Schürig
DESCRIPTION:
This file contains a code resource to be installed as a Trap Patch.
NOTES:
This code is applied as a patch to TEClick.
If text is command clicked it's launched as a URL with the appropriate
helper application.
___________________________________________________________________________
*/
//=============================================================================
// Include files
//-----------------------------------------------------------------------------
#include <Gestalt.h>
#include <ToolUtils.h>
#include <Processes.h>
#include <TextEdit.h>
#include <Notification.h>
#include <LowMem.h>
#include <AppleEvents.h>
#include <ICTypes.h>
#include <ICCAPI.h>
#include <ICKeys.h>
#include "A4Stuff.h"
#include "SetupA4.h"
#include "SignatureToApp.h"
#include "ICeTEe Constants.h"
#include "ICeTEe AddrsTable.h"
//=============================================================================
// Private defines
//-----------------------------------------------------------------------------
#define strMiscErr 1
#define strNoCMErr 2
#define strNoICErr 3
#define strInsufficientICErr 4
#define strNoMemoryErr 5
#define strCantFindHelperErr 6
#define strNoHelperErr 7
#define strNoURLErr 8
#define strCantHackIt 9
#define kICBookmarkHelper "\pHelper•bookmark"
#define kCommandKey 55
#define kOptionKey 58
#define KeyIsDown(k)( ( (km.arr)[k>>3] >> (k & 7) ) & 1)
//=============================================================================
// Types
//-----------------------------------------------------------------------------
typedef pascal void (*TEClickProcPtr)(Point pt, Boolean fExtend, TEHandle teH);
typedef union {
UInt8 arr[16];
KeyMap map;
} KeyMapArr;
//=============================================================================
// Global Variables
//-----------------------------------------------------------------------------
TEClickProcPtr gPrevTEClick;
Handle gExclusions;
Handle gErrors;
AEEventClass gBkEventClass;
AEEventID gBkEventID;
Boolean gAlreadyRan = false;
//=============================================================================
// Private function prototypes
//-----------------------------------------------------------------------------
pascal void main(Point pt, Boolean fExtend, TEHandle teH);
Boolean CurrentProcessExcluded(Handle exclusions);
void MyTEClick(TEHandle teH, short oldSelStart, short oldSelEnd, Boolean makeBookmark);
ICError DoCommandClick(TEHandle teH, long selStart, long selEnd, Boolean makeBookmark);
pascal ICError AddBookmark(internetConfigurationComponent inst, Ptr urlP, long len);
void GetIndStrH(Str255 s, Handle h, short index);
pascal void MyNMResponseProc(NMRecPtr nm);
//=============================================================================
// CurrentProcessExcluded : Check if URL clicking is disabled for this app.
//-----------------------------------------------------------------------------
Boolean CurrentProcessExcluded(Handle exclusions)
{
ProcessSerialNumber PSN;
ProcessInfoRec info;
int i;
Boolean exclude = true;
#if qDebug >= 2
DebugStr("\pCurrentProcessExcluded entered");
#endif
PSN.highLongOfPSN = 0;
PSN.lowLongOfPSN = kCurrentProcess;
info.processInfoLength = sizeof(ProcessInfoRec);
info.processName = nil;
info.processAppSpec = nil;
if ( GetProcessInformation(&PSN, &info) == noErr )
{
exclude = false;
for (i = 0; i < GetHandleSize(exclusions) / sizeof(OSType); i++)
{
if ( (* (OSType **)exclusions)[i] == info.processSignature )
{
exclude = true;
break;
}
}
}
#if qDebug >= 2
DebugStr("\pCurrentProcessExcluded exit");
#endif
return(exclude);
}
//=============================================================================
// GetIndStrH : GetIndString analog for Handles instead of Resources.
//-----------------------------------------------------------------------------
void GetIndStrH(Str255 str, Handle h, short index)
{
#if qDebug >= 2
DebugStr("\pGetIndStrH entered");
#endif
if (h != nil)
{
short count;
short i;
StringPtr strP;
count = **(short**)h;
if ( 1 <= index && index <= count )
{
strP = (StringPtr)*h + sizeof(short);
for (i = 1; i < index; i++)
{
strP += StrLength(strP) + 1;
}
BlockMoveData(strP, str, StrLength(strP) + 1);
}
else
{
str[0] = 0;
}
}
else
{
str[0] = 0;
}
#if qDebug >= 2
DebugStr("\pGetIndStrH exit");
#endif
}
//=============================================================================
// MyNMResponseProc : Notification response & cleanup.
//-----------------------------------------------------------------------------
pascal void MyNMResponseProc(NMRecPtr nm)
{
THz oldZone;
Handle strH;
NMRemove(nm);
oldZone = GetZone();
SetZone(SystemZone());
strH = RecoverHandle((Ptr)(nm->nmStr));
if (strH != nil)
DisposeHandle(strH);
DisposePtr((Ptr)nm);
SetZone(oldZone);
}
//=============================================================================
// MyTEClick : TEClick addition.
//-----------------------------------------------------------------------------
void MyTEClick(TEHandle teH, short oldSelStart, short oldSelEnd, Boolean makeBookmark)
{
ICError err;
#if qDebug >= 1
DebugStr("\pMyTEClick entered");
#endif
if ( !CurrentProcessExcluded(gExclusions) )
{
if ( !( (oldSelStart <= (**teH).selStart) && ((**teH).selStart <= oldSelEnd)
&& (oldSelStart <= (**teH).selEnd) && ((**teH).selEnd <= oldSelEnd) ) )
{
oldSelStart = (**teH).selStart;
oldSelEnd = (**teH).selEnd;
}
err = DoCommandClick(teH, oldSelStart, oldSelEnd, makeBookmark);
if (err != noErr)
{
Str255 errStr;
StringHandle errStrH;
short errStrIdx;
Str32 errNumStr;
NMRecPtr nm;
switch (err) {
case badComponentInstance:
errStrIdx = strNoCMErr;
break;
case badComponentSelector:
errStrIdx = strInsufficientICErr;
break;
case memFullErr:
errStrIdx = strNoMemoryErr;
break;
case afpItemNotFound:
errStrIdx = strCantFindHelperErr;
break;
case icPrefNotFoundErr:
errStrIdx = strNoHelperErr;
break;
case icNoURLErr:
errStrIdx = strNoURLErr;
break;
case noPortErr:
errStrIdx = strCantHackIt;
break;
default:
errStrIdx = strMiscErr;
break;
}
GetIndStrH(errStr, gErrors, errStrIdx);
errStrH = NewString(errStr);
NumToString(err, errNumStr);
Munger((Handle)errStrH, 0, "^0", 2, &errNumStr[1], StrLength(errNumStr));
HLock((Handle)errStrH);
nm = (NMRecPtr)NewPtrSysClear(sizeof(NMRec));
if (nm != nil)
{
nm->qType = nmType;
nm->nmMark = 0;
nm->nmIcon = nil;
nm->nmSound = nil;
nm->nmStr = *errStrH;
nm->nmResp = MyNMResponseProc;
err = NMInstall(nm);
}
else
{
SysBeep(10);
DisposeHandle((Handle)errStrH);
}
}
}
#if qDebug >= 1
DebugStr("\pMyTEClick exit");
#endif
}
//=============================================================================
// DoCommandClick : Handle the click.
//-----------------------------------------------------------------------------
ICError DoCommandClick(TEHandle teH, long selStart, long selEnd, Boolean makeBookmark)
{
ComponentInstance inst;
ICError err, err2;
#if qDebug >= 1
DebugStr("\pDoCommandClick entered");
#endif
err = ICCStart(&inst, kCreator);
if (err == noErr)
{
err = ICCFindConfigFile(inst, 0, nil);
if (err == noErr)
{
Handle textH;
SInt8 s;
StringPtr hint, at;
Handle urlH;
long tmpSelStart = selStart;
long tmpSelEnd = selEnd;
textH = (Handle)TEGetText(teH);
s = HGetState(textH);
HLock(textH);
urlH = NewHandle(0);
hint = "\pmailto";
err = ICCParseURL(inst, hint, *textH, GetHandleSize(textH), &tmpSelStart, &tmpSelEnd, urlH);
if (err == noErr)
{
hint = "\p";
at = "\p@";
if ( Munger(urlH, 0, &at[1], StrLength(at), nil, 0) >= 0 )
{
hint = "\pmailto";
}
if (makeBookmark)
{
err = AddBookmark(inst, (*textH) + tmpSelStart, tmpSelEnd - tmpSelStart);
TESetSelect(tmpSelStart, tmpSelEnd, teH);
}
else
{
err = ICCLaunchURL(inst, hint, *textH, GetHandleSize(textH), &selStart, &selEnd);
TESetSelect(selStart, selEnd, teH);
}
}
DisposeHandle(urlH);
if (err == noErr)
{
SInt32 junk;
SInt16 i = LMGetMenuFlash();
while (i--)
{
Delay(5, &junk);
TEDeactivate(teH);
Delay(5, &junk);
TEActivate(teH);
}
}
HSetState(textH, s);
}
err2 = ICCStop(inst);
if (err == noErr)
err = err2;
}
#if qDebug >= 1
DebugStr("\pDoCommandClick exit");
#endif
return(err);
}
//=============================================================================
// AddBookmark : Send a bookmark event to the bookmark app.
//-----------------------------------------------------------------------------
pascal ICError AddBookmark(internetConfigurationComponent inst, Ptr urlP, long len)
{
ICAttr junkAttr;
ICAppSpec bookmHelper;
long helperSize;
ProcessSerialNumber psn;
ICError err;
#if qDebug >= 1
DebugStr("\pAddBookmark entered");
#endif
helperSize = sizeof(bookmHelper);
err = ICCGetPref(inst, kICBookmarkHelper, &junkAttr, (void *)&bookmHelper, &helperSize);
err = SignatureToApp(bookmHelper.fCreator, nil, &psn, nil, nil,
Sig2App_LaunchApplication, launchContinue | launchDontSwitch);
if (err == noErr)
{
AEAddressDesc target;
err = AECreateDesc(typeProcessSerialNumber, &psn, sizeof(psn), &target);
if (err == noErr)
{
AppleEvent theEvent;
err = AECreateAppleEvent(gBkEventClass, gBkEventID, &target, kAutoGenerateReturnID, kAnyTransactionID, &theEvent);
if (err == noErr)
{
char *u = urlP;
long l = len;
if (u[0] == '<')
{
u++;
l--;
}
if (u[l-1] == '>')
l--;
err = AEPutParamPtr(&theEvent, keyDirectObject, typeChar, u, l);
if (err == noErr)
{
AppleEvent reply;
err = AESend(&theEvent, &reply, kAENoReply, kAEHighPriority, kNoTimeOut, nil, nil);
}
AEDisposeDesc(&theEvent);
}
AEDisposeDesc(&target);
}
}
#if qDebug >= 1
DebugStr("\pAddBookmark exit");
#endif
return err;
}
//=============================================================================
// main : Entry point to our code resource.
//-----------------------------------------------------------------------------
pascal void main(Point pt, Boolean fExtend, TEHandle teH)
{
long oldA4;
short oldSelStart, oldSelEnd;
KeyMapArr km;
Boolean commandKey;
Boolean optionKey;
// Set up A4
#ifndef powerc
oldA4 = SetCurrentA4();
#endif
#if qDebug >= 2
DebugStr("\pICeTEe entered");
#endif
// Save old selection
oldSelStart = (**teH).selStart;
oldSelEnd = (**teH).selEnd;
// Get modifier keys
GetKeys(km.map);
commandKey = KeyIsDown(kCommandKey);
optionKey = KeyIsDown(kOptionKey);
// If we've not already been called, do our one time initialisation stuff
if (!gAlreadyRan)
{
ICeTEeAddressTable *theAddressTable;
Gestalt(kICeTEeAddressTable, (long *) &theAddressTable);
gPrevTEClick = (TEClickProcPtr) ((long) theAddressTable->theTable[kTEClick]);
gExclusions = theAddressTable->exclusions;
gErrors = theAddressTable->errors;
gBkEventClass = theAddressTable->bkEventClass;
gBkEventID = theAddressTable->bkEventID;
gAlreadyRan = true;
}
// Call the original TEClick()
gPrevTEClick(pt, fExtend, teH);
// Do our thing
if (commandKey)
{
THz oldZone;
oldZone = GetZone();
SetZone(SystemZone());
MyTEClick(teH, oldSelStart, oldSelEnd, optionKey);
SetZone(oldZone);
}
#if qDebug >= 2
DebugStr("\pICeTEe exit");
#endif
// Restore A4 and return
#ifndef powerc
SetA4(oldA4);
#endif
}